using UnityEngine;
using System.Collections;
using DanielSig;
using DanielSig.UnityExtensions;

public class Conscience : MonoBehaviour
{
	public LayerMask NoTouching;
	public float NoTouchingRange;
	public float Sensitivity;
	public string EnemyTag;
	
	public float DamagePenalty = 1;
	public float MissPenalty = 1;
	public float HealingReward = 1;
	public float ReloadReward = 1;
	public float EnemyHealingPenalty = 1;
	public float EnemyDamageReward = 1;
	public float MovementReward = 1;
	public float StayStillPenalty = 1;
	
	private Vector3 _prevPos = Vector3.zero;
	private int _standStillCounter = 0;
	
	void ProjectileImpact(float damage)
	{
		float divisor = GetComponentInChildren<HealthSensor>().Health.Max(0.1F);
		if(DamagePenalty > 0)
			SendMessage("Bad", DamagePenalty * Sensitivity * Mathf.Log10(1 + damage / divisor));
	}
	void ProjectileHit(GameObject target)
	{
		if(target.tag != EnemyTag)
		{
			int divisor = GetComponentInChildren<Gun>().AmmoCount.Max(1);
			if(MissPenalty > 0)
				SendMessage("Bad", MissPenalty * Sensitivity / (divisor * 0.1F));
		}
	}
	void AddHealth(float amount)
	{
		float divisor = GetComponentInChildren<HealthSensor>().Health.Max(0.1F);
		if(HealingReward > 0)
			SendMessage("Good", HealingReward * Sensitivity * Mathf.Log10(1 + amount / divisor));
	}
	void AddAmmo(int amount)
	{
		int divisor = GetComponentInChildren<Gun>().AmmoCount.Max(1);
		if(ReloadReward > 0)
			SendMessage("Good", ReloadReward * Sensitivity * Mathf.Log10(1 + amount / (float)divisor));
	}
	
	private FOVSensor _enemyHealthSensor;
	private float _lastKnownEnemyHealth = 1F;
	void Start()
	{
		GameCore.Register(UpdateConscience);
		_enemyHealthSensor = this.GetComponentInChildren<FOVSensor>(s => s.Type == SensationType.EnemyHealth);
	}
	void UpdateConscience()
	{
		if(_enemyHealthSensor)
		{
			if(_enemyHealthSensor.Values[0] < _lastKnownEnemyHealth)
			{
				if(EnemyDamageReward > 0)
					SendMessage("Good", EnemyDamageReward * Sensitivity * (_lastKnownEnemyHealth - _enemyHealthSensor.Values[0]));
			}
			else if(_enemyHealthSensor.Values[0] > _lastKnownEnemyHealth && EnemyHealingPenalty > 0)
				SendMessage("Bad", EnemyHealingPenalty * Sensitivity * (_enemyHealthSensor.Values[0] - _lastKnownEnemyHealth));
			_lastKnownEnemyHealth = _enemyHealthSensor.Values[0];
		}
		if(Physics.Linecast(transform.position, transform.forward * NoTouchingRange, NoTouching.value))
		{
			SendMessage("Bad", Sensitivity);
		}
		if(_prevPos != transform.position)
		{
			if(MovementReward > 0)
				SendMessage("Good", MovementReward * Sensitivity * _prevPos.DistanceToSqr(transform.position));
			_prevPos = transform.position;
			_standStillCounter = 0;
		}
		if(_standStillCounter++ > 10 && StayStillPenalty > 0)
		{
			SendMessage("Bad", StayStillPenalty * Sensitivity * (_standStillCounter - 10) / 5F);
		}
	}
}

